/*
 *  Copright: 2008 Philipp Leitner, Distributed Systems Group,
 *            TU Wien, leitner@infosys.tuwien.ac.at
 *
 *  This file is part of DAIOS.
 *
 *  DAIOS is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation.
 * 
 *  DAIOS is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with DAIOS.  If not, see
 *  <http://www.gnu.org/licenses/>.
 * 
 */

package at.ac.tuwien.infosys.dsg.daios.wsdl.matcher;

import java.util.List;

import at.ac.tuwien.infosys.dsg.daios.exceptions.AmbigiousException;
import at.ac.tuwien.infosys.dsg.daios.framework.structs.DaiosInputMessage;
import at.ac.tuwien.infosys.dsg.daios.framework.structs.DaiosMessage;
import at.ac.tuwien.infosys.dsg.daios.wsdl.impl.WSDLUtil;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDLType;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDLMessage;
import at.ac.tuwien.infosys.dsg.daios.wsdl.interfaces.IWSDLOperation;
import at.ac.tuwien.infosys.dsg.daios.wsdl.typesystem.WSDLTypeTree;

/**
 * The concrete Matcher which is responsible for document-style matching.
 * 
 * @author philipp
 *
 */
public class DocumentWrappedMatcher extends Matcher {
	
	/**
	 * Calculate the distance between a single WSDL message and a
	 * Daios input message.
	 * 
	 * @param message The Daios input message.
	 * @param msgToUse The WSDL message to compare to the Daios message.
	 * @param operations A list of all operations to consider.
	 * @param types A type tree containing all types from the WSDL definition.
	 * @return The distance between the Daios message and the WSDL message as Integer.
	 * 
	 * @throws AmbigiousException 
	 */
	protected int distance(DaiosInputMessage message, IWSDLMessage msgToUse,
			List<IWSDLOperation> operations, WSDLTypeTree types)
		throws AmbigiousException {

		// throw AmbigiousException if msg does not follow doc/wrapped style
		if(!WSDLUtil.wrappedStyle(msgToUse))
			throw new AmbigiousException("WSDL file does not seem to follow "+
				"document/wrapped style. Currently only rpc and document/wrapped "+
				"are supported. Not fitting message is "+msgToUse.getMessageName());
		
		// return MAX if message is no input message
		if(!isInputMessage(msgToUse, operations))
			return MAX_DISTANCE;
		
		// return structural distance between msg and input
		// compared to RPC the distance calculation is a little
		// simpler here - since we have a 'wrapper type' in doc/wrapped
		// we can just calculate the structural distance between
		// the actual message and the wrapper type. The logic for
		// this calculation is already implemented in Daios messages
		String wrapperTypeName = null;
		if(msgToUse.getParts().size() > 0)
			wrapperTypeName = msgToUse.getParts().get(0).getPartType();
		IWSDLType wrapperType = null;
		if(wrapperTypeName != null)
			wrapperType = types.getGlobalElement(wrapperTypeName);
		if(wrapperType != null) {
			DaiosMessage wrap = new DaiosMessage();
			wrap.setComplex(wrapperType.getName().getLocalPart(), message);
			return wrapperType.calculateDistanceToMessage(wrap);
		} else
			return message.structuralDistance(null);
		
	}

}
